home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / C Internet Config / IC Component Debug ƒ / IC Component Source ƒ / IC Resource ƒ / Syslog Component ƒ / Libsprintf.c < prev    next >
Encoding:
Text File  |  1995-11-15  |  13.2 KB  |  641 lines  |  [TEXT/SPM ]

  1. ze : 1;
  2.     unsigned         LSize : 1;
  3.     char            sign;
  4.     char            exponent;
  5.     int                fieldWidth;
  6.     int                precision;
  7. } default_format;
  8.  
  9. #ifndef _NOFLOATING_
  10.  
  11. #include <fp.h>
  12.  
  13. struct LibDecRec {
  14.     decimal    dec;
  15.     /* following fields aren't used by SANE */
  16.     short            min;
  17.     short            dot;
  18.     short            max;
  19. };
  20.  
  21. typedef struct LibDecRec LibDecRec;
  22.  
  23. void libf2d(int, int, struct LibDecRec *, long double);
  24. static void post_conversion(LibDecRec *d);
  25.  
  26. #endif
  27.  
  28. char libstrlen(char* cstr){
  29.     REGISTER char len=0;
  30.     REGISTER char* str=cstr;
  31.     
  32.     if (*str!=0){
  33.         do {
  34.             len++;
  35.             str++;
  36.         } while (*str!=0);
  37.     }
  38.     
  39.     return len;
  40. }
  41.  
  42. void libfixnl(char* buf){
  43.     REGISTER char* cp=buf;
  44.     
  45.     if ((cp==(char*)0)||(*cp==0))
  46.         return;
  47.     
  48.     do {
  49.         if (*cp=='\n')
  50.             *cp=0x06;
  51.         cp++;
  52.     } while (*cp!=0);
  53. }
  54.  
  55. int libsprintf(char *s, const char *fmt, ...){
  56.     return libvsprintf(s, fmt, __va(fmt));
  57. }
  58.  
  59. int libvsprintf(char *cfp,const char *fmt,va_list arg){
  60.     REGISTER int c, i, j, nwritten = 0;
  61.     REGISTER unsigned long n;
  62.     long double x;
  63.     REGISTER char *s;
  64.     REGISTER char* fp=cfp;
  65.     char buf[BUFLEN], *digits, *t;
  66.     char* endbuf;
  67.     struct format F;
  68. #ifndef _NOFLOATING_
  69.     LibDecRec D;
  70. #endif
  71.     
  72.     // buffers containing strings full of zeros and spaces
  73.     char* __gZeroString;
  74.     char* __gSpaceString;
  75.  
  76.     // variables used by libvsprintf
  77.     char __gFloatConst[]="\6>>>>>>";
  78.     char __gCapDigits[]= "0123456789ABCDEF";
  79.     char __gLowDigits[]= "0123456789abcdef";
  80.  
  81.     __gZeroString=(char*)NewPtr(BUFLEN);
  82.     __gSpaceString=(char*)NewPtr(BUFLEN);
  83.     
  84.     for (i=0;i<BUFLEN;i++){
  85.         __gZeroString[i]='0';
  86.         __gSpaceString[i]=' ';
  87.     }
  88.     
  89.     // init default_format
  90.     // this may/may not be necessary (I don't know what some
  91.     // optimizers might be doing; this will ensure correct entries
  92.     
  93.     default_format.leftJustify=FALSE;
  94.     default_format.forceSign=FALSE;
  95.     default_format.altForm=FALSE;
  96.     default_format.zeroPad=FALSE;
  97.     default_format.havePrecision=FALSE;
  98.     default_format.hSize=FALSE;
  99.     default_format.lSize=FALSE;
  100.     default_format.LSize=FALSE;
  101.     default_format.sign=0;
  102.     default_format.exponent=0;
  103.     default_format.fieldWidth=0;
  104.     default_format.precision=0;
  105.     
  106.     s_errno=(long)paramErr;
  107.     
  108.     // only calculate endbuf once
  109.     endbuf=&(buf[BUFLEN]);
  110.     
  111.     for (c = *fmt; c; c = *++fmt) {
  112.         // reset the format
  113.         F = default_format;
  114.         
  115.         if (c != '%'){
  116. #if 1
  117.             s=(char*)fmt;
  118.             
  119.             for (i=0;1;i++){
  120.                 if ((fmt[i]=='%')||(fmt[i]==0)){
  121.                     // i points at a terminator
  122.                     // allow the rest of the function to copy the string n stuff
  123.                     fmt+=(i-1);
  124.                     goto EndOfSwitch;
  125.                 }
  126.             }
  127. #else
  128.             goto copy1;
  129. #endif
  130.         }
  131.         
  132.             /*  decode flags  */
  133.             
  134.         for (;;) {
  135.             c = *++fmt;
  136.             if (c == '-')
  137.                 F.leftJustify = TRUE;
  138.             else if (c == '+')
  139.                 F.forceSign = TRUE;
  140.             else if (c == ' ')
  141.                 F.sign = ' ';
  142.             else if (c == '#')
  143.                 F.altForm = TRUE;
  144.             else if (c == '0')
  145.                 F.zeroPad = TRUE;
  146.             else
  147.                 break;
  148.         }
  149.         
  150.             /*  decode field width  */
  151.             
  152.         if (c == '*') {
  153.             if ((F.fieldWidth = va_arg(arg, int)) < 0) {
  154.                 F.leftJustify = TRUE;
  155.                 F.fieldWidth = -F.fieldWidth;
  156.             }
  157.             c = *++fmt;
  158.         } else {
  159.             for (; c >= '0' && c <= '9'; c = *++fmt)
  160.                 F.fieldWidth = (10 * F.fieldWidth) + (c - '0');
  161.         }
  162.         
  163.             /*  decode precision  */
  164.             
  165.         if (c == '.') {
  166.             if ((c = *++fmt) == '*') {
  167.                 F.precision = va_arg(arg, int);
  168.                 c = *++fmt;
  169.             } else {
  170.                 for (; c >= '0' && c <= '9'; c = *++fmt)
  171.                     F.precision = (10 * F.precision) + (c - '0');
  172.             }
  173.             if (F.precision >= 0)
  174.                 F.havePrecision = TRUE;
  175.         }
  176.         
  177.             /* decode size modifiers */
  178.             
  179.         while ((c=='h')||(c=='l')||(c=='L')){
  180.             if (c=='h')
  181.                 F.hSize=TRUE;
  182.             else if (c=='l')
  183.                 F.lSize=TRUE;
  184.             else
  185.                 F.LSize=TRUE;
  186.             
  187.             c=*++fmt;
  188.         }
  189.         
  190.             /*  perform appropriate conversion  */
  191.         
  192.         s =endbuf;
  193.         if (F.leftJustify)
  194.             F.zeroPad = FALSE;
  195.         
  196. conv:    switch (c) {
  197.                 
  198.                 /*  decimal (signed)  */
  199.                 
  200.             case 'd':
  201.             case 'i':
  202.                 if (F.lSize)
  203.                     n = va_arg(arg, long);
  204.                 else
  205.                     n = va_arg(arg, int);
  206.                 if (F.hSize)
  207.                     n = (short) n;
  208.                 if ((long) n < 0) {
  209.                     n = -n;
  210.                     F.sign = '-';
  211.                 } else if (F.forceSign)
  212.                     F.sign = '+';
  213.                 goto decimal;
  214.                 
  215.                 /*  decimal (unsigned)  */
  216.                 
  217.             case 'u':
  218.                 if (F.lSize)
  219.                     n = va_arg(arg, unsigned long);
  220.                 else
  221.                     n = va_arg(arg, unsigned int);
  222.                 if (F.hSize)
  223.                     n = (unsigned short) n;
  224.                 F.sign = 0;
  225.                 goto decimal;
  226.                 
  227.                 /*  decimal (common code)  */
  228.  
  229. decimal:
  230.                 if (!F.havePrecision) {
  231.                     if (F.zeroPad) {
  232.                         F.precision = F.fieldWidth;
  233.                         if (F.sign)
  234.                             --F.precision;
  235.                     }
  236.                     if (F.precision < 1)
  237.                         F.precision = 1;
  238.                 }
  239.                 for (i = 0; n; n /= 10, i++)
  240.                     *--s = n % 10 + '0';
  241.                 if (i<F.precision){
  242.                     j=(F.precision-i);
  243.                     s-=j;
  244.                     BlockMoveData((Ptr)__gZeroString,(Ptr)s,j);
  245.                     i=F.precision;
  246.                 }
  247.                 if (F.sign) {
  248.                     *--s = F.sign;
  249.                     i++;
  250.                 }
  251.                 break;
  252.                 
  253.                 /*  octal (unsigned)  */
  254.                 
  255.             case 'o':
  256.                 if (F.lSize)
  257.                     n = va_arg(arg, unsigned long);
  258.                 else
  259.                     n = va_arg(arg, unsigned int);
  260.                 if (F.hSize)
  261.                     n = (unsigned short) n;
  262.                 if (!F.havePrecision) {
  263.                     if (F.zeroPad)
  264.                         F.precision = F.fieldWidth;
  265.                     if (F.precision < 1)
  266.                         F.precision = 1;
  267.                 }
  268.                 for (i = 0; n; n /= 8, i++)
  269.                     *--s = n % 8 + '0';
  270.                 if (F.altForm && i && *s != '0') {
  271.                     *--s = '0';
  272.                     i++;
  273.                 }
  274.                 if (i<F.precision){
  275.                     j=(F.precision-i);
  276.                     s-=j;
  277.                     BlockMoveData((Ptr)__gZeroString,(Ptr)s,j);
  278.                     i=F.precision;
  279.                 }
  280.                 break;
  281.                 
  282.                 /*  hexadecimal (unsigned)  */
  283.                 
  284.             case 'p': // pointer processing
  285.                 F.havePrecision = F.lSize = TRUE;
  286.                 F.precision = 8;
  287.                 /* ... */
  288.             case 'X':
  289.                 digits = __gCapDigits;
  290.                 goto hexadecimal;
  291.             case 'x':
  292.                 digits =__gLowDigits;
  293.                 /* ... */
  294. hexadecimal:
  295.                 if (F.lSize)
  296.                     n = va_arg(arg, unsigned long);
  297.                 else
  298.                     n = va_arg(arg, unsigned int);
  299.                 if (F.hSize)
  300.                     n = (unsigned short) n;
  301.                 if (!F.havePrecision) {
  302.                     if (F.zeroPad) {
  303.                         F.precision = F.fieldWidth;
  304.                         if (F.altForm)
  305.                             F.precision -= 2;
  306.                     }
  307.                     if (F.precision < 1)
  308.                         F.precision = 1;
  309.                 }
  310.                 for (i = 0; n; n /= 16, i++)
  311.                     *--s = digits[n % 16];
  312.                 if (i<F.precision){
  313.                     j=(F.precision-i);
  314.                     s-=j;
  315.                     BlockMoveData((Ptr)__gZeroString,(Ptr)s,j);
  316.                     i=F.precision;
  317.                 }
  318.                 if (F.altForm) {
  319.                     *--s = c;
  320.                     *--s = '0';
  321.                     i += 2;
  322.                 }
  323.                 break;
  324.                 
  325.  
  326.                 /*  character  */
  327.                 
  328.             case 'c':
  329.                 *--s = va_arg(arg, int);
  330.                 i = 1;
  331.                 break;
  332.                 
  333.                 /*  Error  */
  334.             case 'm':
  335.                 // display the error stored in errno (s_errno);
  336.                 s=buf;
  337.                 i=libsprintf(buf,"%ld",s_errno);
  338.                 break;
  339.                 
  340.                 /*  string  */
  341.                 
  342.             case 's':
  343.                 s = va_arg(arg, char *);
  344.                 i=0;
  345.                 if (F.altForm) {
  346.                     unsigned char* ucp=(unsigned char*)s;
  347.                     unsigned char uc=*ucp;
  348.                     
  349.                     s++;
  350.                     i=(int)0;
  351.                     i+=uc;
  352.                 } else {
  353.                     i = libstrlen(s);
  354.                 }
  355.                 
  356.                 if ((F.havePrecision)&&(i>F.precision))
  357.                     i=F.precision;
  358.                 
  359.                 break;
  360.                 
  361. #ifndef _NOFLOATING_
  362.                 /*  fixed-point  */
  363.  
  364.             case 'f':
  365.                 if (F.LSize)
  366.                     x = va_arg(arg, long double);
  367.                 else
  368.                     x = va_arg(arg, double);
  369.                 if (!F.havePrecision)
  370.                     F.precision = 6;
  371.                 libf2d(1, F.precision, (LibDecRec*)&D, x);
  372.                 D.dot = D.dec.exp + D.dec.sig.length;
  373.                 if ((D.min = D.dot) > 1)
  374.                     D.min = 1;
  375.                 D.max = D.dot + F.precision;
  376.                 if (D.max - D.min > 508)
  377.                     BlockMoveData((Ptr)__gFloatConst,(Ptr)&D.dec.sig, 7);
  378.                 goto floating;
  379.  
  380.                 /*  floating-point  */
  381.                 
  382.             case 'e':
  383.             case 'E':
  384.                 if (F.LSize)
  385.                     x = va_arg(arg, long double);
  386.                 else
  387.                     x = va_arg(arg, double);
  388.                 if (!F.havePrecision)
  389.                     F.precision = 6;
  390.                 F.exponent = c;
  391.                 libf2d(0, D.max = F.precision + 1,  (LibDecRec*)&D, x);
  392.                 D.min = D.dot = 1;
  393.                 D.dec.exp += D.dec.sig.length - 1;
  394.                 goto floating;
  395.                 
  396.                 /*  "general" notation  */
  397.                 
  398.             case 'g':
  399.             case 'G':
  400.                 if (F.LSize)
  401.                     x = va_arg(arg, long double);
  402.                 else
  403.                     x = va_arg(arg, double);
  404.                 if (!F.havePrecision)
  405.                     F.precision = 6;
  406.                 else if (F.precision == 0)
  407.                     F.precision = 1;
  408.                 F.exponent = c - 2;
  409.                 libf2d(0, D.max = F.precision, (LibDecRec*) &D, x);
  410.                 D.min = D.dot = 1;
  411.                 D.dec.exp += D.dec.sig.length - 1;
  412.                 if (D.dec.exp >= -4 && D.dec.exp < F.precision) {
  413.                     F.exponent = 0;
  414.                     if ((D.dot += D.dec.exp) < 1)
  415.                         D.min = D.dot;
  416.                 }
  417.                 if (!F.altForm && D.max > D.dec.sig.length) {
  418.                     if ((D.max = D.dec.sig.length) < D.dot)
  419.                         D.max = D.dot;
  420.                 }
  421.                 goto floating;
  422.                 
  423.                     /*  floating (common code)  */
  424.  
  425. floating:
  426.                 if (D.dec.sig.text[0] > '9') {
  427.                     F.exponent = FALSE;
  428.                     D.dot = 0;
  429.                     D.min = 1;
  430.                     D.max = D.dec.sig.length;
  431.                 }
  432.                 i = 0;
  433.                 if (F.exponent) {
  434.                     n = D.dec.exp < 0 ? -D.dec.exp : D.dec.exp;
  435.                     for (; n; n /= 10, i++)
  436.                         *--s = n % 10 + '0';
  437.                     for (; i < 2; i++)
  438.                         *--s = '0';
  439.                     *--s = D.dec.exp < 0 ? '-' : '+';
  440.                     *--s = F.exponent;
  441.                     i += 2;
  442.                 }
  443.                 j = D.max;
  444.                 if (j == D.dot && !F.altForm)
  445.                     ++D.dot;
  446.                 do {
  447.                     if (j == D.dot) {
  448.                         *--s = '.';
  449.                         i++;
  450.                     }
  451.                     *--s = j > 0 && j <= D.dec.sig.length ? D.dec.sig.text[j-1] : '0';
  452.                 } while (--j >= D.min);
  453.                 i += D.max - j;
  454.                 if (D.dec.sgn)
  455.                     F.sign = '-';
  456.                 else if (F.forceSign)
  457.                     F.sign = '+';
  458.                 if (F.zeroPad) {
  459.                     j = F.fieldWidth;
  460.                     if (F.sign)
  461.                         --j;
  462.                     if (i<j){
  463.                         s -= (j-i);
  464.                         
  465.                         BlockMoveData((Ptr)__gZeroString,(Ptr)s,(j-i));
  466.                         i=j;
  467.                     }
  468.                 }
  469.                 if (F.sign) {
  470.                     *--s = F.sign;
  471.                     i++;
  472.                 }
  473.                 break;
  474. #endif /* _NOFLOATING_ */
  475.                 /*  store # bytes written so far  */
  476.                 
  477.             case 'n':
  478.                 s = (char *)va_arg(arg, void *);
  479.                 if (F.hSize)
  480.                     * (short *) s = nwritten;
  481.                 else if (F.lSize)
  482.                     * (long *) s = nwritten;
  483.                 else
  484.                     * (int *) s = nwritten;
  485.                 continue;
  486.             
  487.                 /*  oops - unknown conversion, abort  */
  488.                 
  489.             default:
  490.                 if (c != '%')
  491.                     goto done;
  492.             copy1:
  493.                 *fp=c;fp++;
  494.                 ++nwritten;
  495.                 continue;
  496.         }
  497.             
  498. EndOfSwitch:
  499.             /*  pad on the left  */
  500.             
  501.         if (i < F.fieldWidth && !F.leftJustify) {
  502.             j=F.fieldWidth-i;
  503.             
  504.             BlockMoveData((Ptr)__gSpaceString,(Ptr)fp,j);
  505.             
  506.             fp+=j;
  507.             nwritten+=j;
  508.             F.fieldWidth=0;
  509.         }
  510.         
  511.             /*  write the converted result  */
  512.         
  513.         BlockMoveData((Ptr)s,(Ptr)fp,i);
  514.         fp+=i;
  515.         nwritten += i;
  516.             
  517.             /*  pad on the right  */
  518.             
  519.         if (i<F.fieldWidth){
  520.             j=F.fieldWidth-i;
  521.             
  522.             BlockMoveData((Ptr)__gSpaceString,(Ptr)fp,j);
  523.             fp+=j;
  524.             nwritten+=j;
  525.         }
  526.     }
  527.     
  528.         /*  all done!  */
  529.         
  530. done:
  531.     *fp=0;
  532.     return nwritten;
  533. }
  534.  
  535. #ifndef _NOFLOATING_
  536.  
  537. static void post_conversion(LibDecRec *d){
  538.     int i;
  539.     /*  strip trailing zeroes  */
  540.  
  541.     for (i = d->dec.sig.length; i > 1 && d->dec.sig.text[i-1] == '0'; --i)
  542.         ++d->dec.exp;
  543.     d->dec.sig.length = i;
  544.         
  545.         /*  format 0, INF, NAN  */
  546.         
  547.     if (d->dec.sig.text[0] == '0') {
  548. /*        d->dec.sgn = 0;             add back to disallow printing "-0"  */
  549.         d->dec.exp = 0;
  550.     }
  551.     else if (d->dec.sig.text[0] == 'I') {
  552.         d->dec.sig.length = 3;
  553.         d->dec.sig.text[1] = 'N';
  554.         d->dec.sig.text[2] = 'F';
  555.     }
  556.     else if (d->dec.sig.text[0] == 'N') {
  557.         d->dec.sig.length = 5;
  558.         d->dec.sig.text[1] = 'A';
  559.         d->dec.sig.text[2] = 'N';
  560.     }
  561. }
  562.  
  563. /* ---------- floating-point conversion ---------- */
  564.  
  565. #if powerc
  566. static void libf2d( int fixed, int precision, LibDecRec *d, long double x){
  567.     struct decform form;
  568.     
  569.     if (precision >= sizeof d->dec.sig)
  570.         precision = sizeof d->dec.sig - 1;
  571.  
  572.     if (fixed)
  573.         form.style = FIXEDDECIMAL;
  574.     else
  575.         form.style = FLOATDECIMAL;
  576.     form.digits = precision;
  577.     /*
  578.         Until the long double data type is really implemented, this must be a call
  579.         to num2dec and not num2decl even though the argument is declared as a long
  580.         double 
  581.     */
  582.     
  583.     num2dec( &form, x, &(d->dec) );
  584.     
  585.         /*  handle fixed-point overflow  */
  586.         
  587.     if (d->dec.sig.text[0] == '?') {
  588.         form.style = FLOATDECIMAL;
  589.         form.digits = sizeof d->dec.sig - 1;
  590.         num2dec( &form, x, &(d->dec));
  591.     }
  592.     post_conversion(d);
  593. #else
  594.  
  595. static void libf2d(int fixed, int precision, LibDecRec *d, long double x){
  596.     struct { char style; short digits; } form;
  597.     REGISTER short *p = (short *) &x;
  598.     
  599.         /*  point to SANE extended  */
  600.  
  601.     #if __option(mc68881) && _NATIVE_FP_
  602.         p[1] = p[0];
  603.     #endif
  604.     #if __option(mc68881) || !_NATIVE_FP_
  605.         p++;
  606.     #endif
  607.     
  608.         /*  convert to decimal record  */
  609.     
  610.     if (precision >= sizeof d->dec.sig)
  611.         precision = sizeof d->dec.sig - 1;
  612.     form.style = fixed;
  613.     form.digits = precision;
  614.     fp68k(&form, p, d, FX2DEC);
  615.     
  616.         /*  handle fixed-point overflow  */
  617.         
  618.     if (d->dec.sig.text[0] == '?') {
  619.         form.style = 0;
  620.         form.digits = sizeof d->dec.sig - 1;
  621.         fp68k(&form, p, d, FX2DEC);
  622.     }
  623.     
  624.     post_conversion(d);    
  625.  
  626. }
  627. #endif // __powerc
  628. #endif // no floating
  629. #endif // use ansi
  630.  
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639.  
  640.